<?php

namespace AgilePayments\Alipay;

use AgilePayments\Config;
use AgilePayments\Extend\Alipay\AopClient;
use AgilePayments\Extend\Alipay\AopCertClient;
use AgilePayments\Extend\Alipay\Request\AlipayTradeQueryRequest;
use think\Request;
use AgilePayments\Tool;

class Service
{
    private $config;

    private $app_id;

    private $appCertPath;

    private $alipayCertPath;

    private $rootCertPath;

    private $rsaPrivateKey;

    private $alipayrsaPublicKey;

    public function __construct(Config $config)
    {
        $this->config = $config;
        $this->appCertPath = Tool::getRootPath() . $this->config->pay_type_config->server_pub_cert;
        $this->alipayCertPath = Tool::getRootPath() . $this->config->pay_type_config->pay_pub_cert;
        $this->rootCertPath = Tool::getRootPath() . $this->config->pay_type_config->root_cert;
        $this->app_id = $this->config->pay_type_config->app_id;
        $this->rsaPrivateKey = $this->config->pay_type_config->server_pri_value;
        $this->alipayrsaPublicKey = $this->config->pay_type_config->pay_pub_value;
        if ($this->config->pay_type_config->type == 1){
            $this->aop = new AopClient ();
            $this->aop->alipayrsaPublicKey = $this->config->pay_type_config->pay_pub_value;
        }else{
            $this->aop = new AopCertClient ();
            $appCertPath = $this->appCertPath;
            $alipayCertPath = $this->alipayCertPath;
            $rootCertPath = $this->rootCertPath;
            $this->aop->alipayrsaPublicKey = $this->aop->getPublicKey($alipayCertPath);//调用getPublicKey从支付宝公钥证书中提取公钥
            $this->aop->isCheckAlipayPublicCert = true;//是否校验自动下载的支付宝公钥证书，如果开启校验要保证支付宝根证书在有效期内
            $this->aop->appCertSN = $this->aop->getCertSN($appCertPath);//调用getCertSN获取证书序列号
            $this->aop->alipayRootCertSN = $this->aop->getRootCertSN($rootCertPath);//调用getRootCertSN获取支付宝根证书序列号
        }
        $this->aop->rsaPrivateKey = $this->rsaPrivateKey;
        $this->aop->gatewayUrl = 'https://openapi.alipay.com/gateway.do';
        $this->aop->appId = $this->app_id;
        $this->aop->apiVersion = '1.0';
        $this->aop->signType = 'RSA2';
        $this->aop->postCharset = 'utf-8';
        $this->aop->format = 'json';
        $is_sandbox = $config->pay_type_config->is_sandbox??2;
        if ($is_sandbox == 1){
            $this->aop->gatewayUrl = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do';
        }
    }

    /**
     * 支付
     * @param string    $notify_url
     * @param string    $order_no
     * @param int       $pay_price
     * @param string    $out_time
     * @param array     $extra_param
     * @param string    $title
     * @return void
     */
public function pay(string $order_no, int $pay_price, string $out_time, string $notify_url, array $extra_param = [], string $title = '', $type = 'APP')
    {
        if ($type == "APP"){
            $object = new \stdClass();
            $object->out_trade_no = $order_no;
            $object->total_amount = bcdiv($pay_price,100,2);
            $object->subject = $title??$order_no;
            $object->product_code ='QUICK_MSECURITY_PAY';
            $object->time_expire = date('Y-m-d H:i:s', $out_time);
            $object->body = $extra_param;
            $json = json_encode($object);
            $request = new \AgilePayments\Extend\Alipay\Request\AlipayTradeAppPayRequest();
            $request->setNotifyUrl($notify_url);
            $request->setBizContent($json);
            $orderString = $this->aop->sdkExecute ($request);
        }else{
            // $this->aop->gatewayUrl = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do';
            $object = new \stdClass();
            $object->out_trade_no = $order_no;
            $object->total_amount = bcdiv($pay_price,100,2);
            $object->subject = $title??$order_no;
            $object->product_code ='QUICK_WAP_WAY';
            $object->time_expire = date('Y-m-d H:i:s', $out_time);
            $object->quit_url = 'https://api.headcollect.com/quit_url';
            $object->body = $extra_param;
            $json = json_encode($object,JSON_UNESCAPED_SLASHES);
            $request = new \AgilePayments\Extend\Alipay\Request\AlipayTradeWapPayRequest();
            $request->setReturnUrl('https://api.headcollect.com/return_url');
            $request->setNotifyUrl($notify_url);
            $request->setBizContent(str_replace('"','\'',$json));
            $orderString = $this->aop->pageExecute($request,"POST");
        }
        return [
            'status'    => true,
            'msg'       => 'success',
            'data'      => ['appPayRequest'=>$orderString,'pay_type'=>$this->config->pay_type],
        ];
    }

    public function refund($payInfo, $notify = '')
    {
        $object = new \stdClass();
        $object->out_trade_no = $payInfo['out_order_id'];
        $object->refund_amount = bcdiv($payInfo['pay_amount'],100,2);
        $object->out_request_no = $payInfo['refund_order_no']; // 部分退款订单号
        Tool::log($payInfo,'info','alipayRefund');
        $json = json_encode($object);
        $request = new \AgilePayments\Extend\Alipay\Request\AlipayTradeRefundRequest();
        $request->setBizContent($json);

        $result = $this->aop->execute ( $request);

        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode)&&$resultCode == 10000){
            return ['status'=>true, 'msg'=>$result->$responseNode->msg,'data'=>json_encode($result->$responseNode)];
        } else {
            return ['status'=>false, 'msg'=>$result->$responseNode->sub_msg,'data'=>json_encode($result->$responseNode)];
        }

    }

    public function refundQuery($refund_no, $trade_no, $date = '')
    {
        $object = new \stdClass();
        $object->trade_no = $trade_no;
        $object->out_request_no =  $refund_no; // 部分退款订单号
        $json = json_encode($object);
        $request = new \AgilePayments\Extend\Alipay\Request\AlipayTradeFastpayRefundQueryRequest();
        $request->setBizContent($json);
        $result =$this->aop->execute ( $request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode)&&$resultCode == 10000){
            return [
                'status'    => true,
                'msg'       => $result->$responseNode->msg,
                'data'      => $result->$responseNode,
            ];
        } else {
            return [
                'status'    => false,
                'msg'       => $result->$responseNode->sub_msg,
                'data'      => $result->$responseNode,
            ];
        }

    }

    /**
     * @deac 交易查询
     * @param $trade_no
     * @return void
     * @throws \Exception
     */
    public function query($trade_no)
    {
        $object = new \stdClass();
        $object->trade_no = $trade_no;
        $json = json_encode($object);
        $request = new \AgilePayments\Extend\Alipay\Request\AlipayTradeQueryRequest();
        $request->setBizContent($json);
        $result =$this->aop->execute ( $request);
        $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
        $resultCode = $result->$responseNode->code;
        if(!empty($resultCode)&&$resultCode == 10000){
            return [
                'status'    => true,
                'msg'       => $result->$responseNode->msg,
                'data'      => $result->$responseNode,
            ];
        } else {
            return [
                'status'    => false,
                'msg'       => $result->$responseNode->sub_msg,
                'data'      => $result->$responseNode,
            ];
        }


    }

    /**
     * @desc 回调验证数据
     */
    public function verifySign($request)
    {
        $data = $_POST;
        unset($data['payType']);
        $status = $this->aop->rsaCheckV1($data,$this->config->pay_type_config->pay_pub_cert,$this->aop->signType);
        if ($status){
            $status = true;
        }else{
            $status = false;
        }
        return [
            'status'        => $status,
            'payOrderId'    => $_POST['out_trade_no']??'', // order_id
            'trade_no'      => $_POST['trade_no']??'',
            'query_id'      => $_POST['queryId']??'',
            'data'          => $_POST??[],
        ];

    }

    public function getUserId($code)
    {
        $request = new \AgilePayments\Extend\Alipay\Request\AlipaySystemOauthTokenRequest();
        $request->setCode($code);
        $request->setGrantType("authorization_code");
        $responseResult = $this->aop->execute($request);
        if (!isset($responseResult->error_response)){
            $responseApiName = str_replace(".","_",$request->getApiMethodName())."_response";
            $response = $responseResult->$responseApiName;
            return [
                'status'    => true,
                'msg'       => 'success',
                'data'      => $response->user_id
            ];
        }else{
            return [
                'status'    => false,
                'msg'       => $responseResult->error_response->sub_msg,
                'data'      => '',
            ];
        }
    }
    public function returnSuccess()
    {
        echo 'success';
    }

}